from functools import lru_cache
from typing import List, Union
from elasticsearch import Elasticsearch, exceptions

from setting import config

__all__ = ['get_es']


class Elastic(object):
    def __init__(self, hosts: List = None, scheme: str = "http", port: int = 9200, username: str = None,
                 password: str = None, sniff_on_start: bool = False, sniff_on_connection_fail: bool = False,
                 sniffer_timeout: int = 10, timeout: int = 180):
        self.hosts = hosts or ['127.0.0.1']
        self.port = port
        self.scheme = scheme
        self.username = username
        self.password = password
        self.sniff_on_start = sniff_on_start
        self.sniff_on_connection_fail = sniff_on_connection_fail
        self.sniffer_timeout = sniffer_timeout
        self.timeout = timeout
        self.es = self.init()

    def init(self) -> Union[Elasticsearch, None]:
        try:
            if self.username or self.password:
                es = Elasticsearch(hosts=self.hosts,
                                   port=self.port,
                                   scheme=self.scheme,
                                   http_auth=(self.username, self.password),
                                   # 在做任何操作之前，先进行嗅探
                                   # sniff_on_start=self.sniff_on_start,
                                   # # 节点没有响应时，进行刷新，重新连接
                                   # sniff_on_connection_fail=self.sniff_on_connection_fail,
                                   # # 每多少秒刷新一次
                                   # sniffer_timeout=self.sniffer_timeout,
                                   timeout=self.timeout)
            else:
                es = Elasticsearch(hosts=self.hosts,
                                   port=self.port,
                                   scheme=self.scheme,
                                   sniff_on_start=self.sniff_on_start,
                                   sniff_on_connection_fail=self.sniff_on_connection_fail,
                                   sniffer_timeout=self.sniffer_timeout,
                                   timeout=self.timeout)
            return es
        except exceptions:
            return None

    def cluster_info(self):
        """
        获取集群基本信息
        """
        if self.es:
            return self.es.info()
        else:
            return None

    def cluster_health(self):
        """
        获取集群健康状态
        """
        if self.es:
            return self.es.cluster.health()
        else:
            return None

    def cluster_indices(self):
        """
        获取集群索引信息
        """
        if self.es:
            return self.es.cat.indices(format='json')
        else:
            return None


@lru_cache
def get_es() -> Elasticsearch:
    """
    获取 ES Client 对象
    """
    if config.ELASTIC_USERNAME and config.ELASTIC_PASSWORD:
        es = Elastic(hosts=config.ELASTIC_HOST, scheme=config.ELASTIC_SCHEME, port=config.ELASTIC_PORT,
                     username=config.ELASTIC_USERNAME, password=config.ELASTIC_PASSWORD)
    else:
        es = Elastic(hosts=config.ELASTIC_HOST, scheme=config.ELASTIC_SCHEME, port=config.ELASTIC_PORT)
    return es.init()


def get_task_es() -> Elasticsearch:
    """
    获取 ES Client 对象
    """
    if config.ELASTIC_USERNAME and config.ELASTIC_PASSWORD:
        es = Elastic(hosts=config.ELASTIC_HOST, scheme=config.ELASTIC_SCHEME, port=config.ELASTIC_PORT,
                     username=config.ELASTIC_USERNAME, password=config.ELASTIC_PASSWORD)
    else:
        es = Elastic(hosts=config.ELASTIC_HOST, scheme=config.ELASTIC_SCHEME, port=config.ELASTIC_PORT)
    return es.init()


if __name__ == '__main__':
    from pprint import pprint

    # elastic = Elastic(hosts=['120.79.89.34'], username="elastic", password="q5f2qNfUJQyvZPIz57MZ")
    # elastic = Elastic(hosts=['106.52.172.23'], username="elastic", password="q5f2qNfUJQyvZPIz57MZ")
    elastic = Elastic(hosts=['192.168.31.11'])
    pprint(elastic.cluster_health())

    elastic = get_es()
    pprint(elastic.cluster.health())

    # data = elastic.es.sql.query(body={'query': 'select fields.app from "logstash-java-*" group by fields.app'})
    # columns = [item.get("name") for item in data.get('columns')]
    #
    # import pandas as pd
    # data = pd.DataFrame(data=data.get("rows"),columns=columns)
    # pprint(data.to_dict(orient='records'))
    #

    # import requests
    #
    #
    # url = "http://106.52.172.23:9200/_nlpcn/sql"
    #
    # payload = "select /*! TRACK_TOTAL_HITS(true) */ * from logstash-java-* limit 1"
    # headers = {
    #     'Content-Type': 'application/json',
    #     'Authorization': 'Basic ZWxhc3RpYzpxNWYycU5mVUpReXZaUEl6NTdNWg=='
    # }
    #
    # response = requests.request("GET", url, headers=headers, data=payload)
    #
    # pprint(response.json())
